home *** CD-ROM | disk | FTP | other *** search
- /*
- * file: Qwertytunes.c
- *
- * started 22 January 1992
- * david van brink
- *
- */
-
-
- /*--------------------------
- Inclusions
- --------------------------*/
-
- #include <QuickDraw.h>
- #include <GestaltEqu.h>
- #include <Windows.h>
- #include <OSEvents.h>
- #include <Memory.h>
- #include <Packages.h>
- #include <Midi.h>
-
- #include "BigEasy2.h"
- #include "BigEasyTextish.h"
- #include "BigEasyGrafish.h"
- #include "BigEasyDialogs.h"
- #include "BigEasyUtils.h"
-
- #define globals
- #include "Qwertytunes.h"
- #include "Qwertytunes Filing.h"
-
- /*--------------------------
- Limits and Konstants
- --------------------------*/
-
-
- enum
- {
- mNew = 100,
- mOpen,
- mSave,
-
- mFirstDocActive,
-
- mClose,
- mSaveAs,
- mBackgroundPlay,
- mSelectInstrument,
- mSelectChannel,
- mMIDIMessage,
-
- mPortList,
- mLastPortListItem = mPortList + kMaxPortCount,
-
- mQwertytunes,
- mLast
- };
-
-
- /*--------------------------
- Types and globals
- --------------------------*/
-
- #define kDocMargin 10
- #define kTextAllowance 16
-
- #define kKeyWidth 23
- #define kKeyHeight 21
- #define kKeyMargin 6
- #define kKeyRowBump 7
- #define kKeyInfoWidth 120
- #define kKeyInfoHeight (4 * kTextAllowance + kDocMargin)
- #define kKeyInfoHDivider 60
-
- #define kSliderThickness kDocMargin
-
- #define kCursorBlinkTicks 14
-
- #define SignIt(x) ( (x)?1:-1)
-
- /*--------------------------
- Prototypes
- --------------------------*/
- static void DrawDoc(short n);
- static void ClickDoc(short n,Point p,short mods);
- static void KeyDoc(short n,short key,short code, short mods);
- static void MoveDoc(short n);
- static void ZoomDoc(short n);
- static short CloseDoc(short n);
- static void IdleDoc(short n,Boolean front);
- static void BackgroundPlayDoc(short n,short item, short ref);
- static void SelectInstrumentDoc(short n,short item, short ref);
- static void SelectChannelDoc(short n,short item, short ref);
- static void MIDIMessageDoc(short n,short item, short ref);
- static void LetsQuit(void);
- static void OpenAWindow(void);
- static void NewDoc(void);
- static void MakeWindow(void);
- static void About(void);
- static void InitVars(void);
- static void SelectKeyDoc(TDoc *d,short key);
- static void Draw1Key(TDoc *d,short n);
- static void DrawKeyInfoDoc(TDoc *d);
- static void DrawKeyNumbersDoc(TDoc *d);
- static void FrameNumbersField(Rect *r);
- static void SelectFieldDoc(TDoc *d,short f);
- static void BlinkTextCursorDoc(TDoc *d,short what);
- static void MIDIConnectDoc(short n,short item, short ref);
- static void DrawNoteName(short noteNumber);
-
- static void FixUpPortListMenu(TDoc *d);
- static void TrackMIDIController(short n,Point p,short controller,TDoc *d);
-
- static pascal void PeriodicThing(long currentTime, long refCon);
- static void SquelchAllKeys(TDoc *d);
-
- /*--------------------------
- Computer Programs
- --------------------------*/
-
- char dKeyPositionToKeyCode[kKeyCount] =
- {
- 18,19,20,21,23,22,26,28,25,29, /* 1234567890 */
- 12,13,14,15,17,16,32,34,31,35, /* qwertyuiop */
- 0, 1, 2, 3, 5, 4,38,40,37,41, /* asdfghjkl; */
- 6, 7, 8, 9,11,45,46,43,47,44 /* zxcvbnm,./ */
- };
-
- char dKeyPositionToKeyName[kKeyCount] = "1234567890QWERTYUIOPASDFGHJKL;ZXCVBNM,./";
-
-
- static short GetModKeys(void);
- short GetModKeys(void)
- /*
- * return the modifier keys just like in an eventrecord
- */
- {
- short result;
- KeyMap keys;
-
- GetKeys(keys);
-
- result = 0;
- if(keys[1] & 1)
- result |= shiftKey;
- if(keys[1] & 4)
- result |= optionKey;
- if(keys[1] & 8)
- result |= controlKey;
- if(keys[1] & 0x8000)
- result |= cmdKey;
-
- return result;
- }
-
-
-
- void DrawDoc(short n)
- /*
- * Draws the window.
- */
- {
- Rect *r,re;
- short i;
- TDoc *d;
- char name;
-
- d = &gDoc[n-kFirstDocWindow];
-
- RGBBack(40000,63000,40000);
- EraseRect(&gBigRect);
-
- GoBW();
- TextSize(9);
- TextFont(3);
- for(i = 0; i < kKeyCount; i++)
- Draw1Key(d,i);
-
- for(i = 0; i < kControllerCount; i++)
- {
- re = g->controllerRect[i];
- FrameRect(&re);
- InsetRect(&re,1,1);
- EraseRect(&re);
- }
-
- if(d->sr.zoomed)
- {
- short y;
-
- GoBW();
- PenPat(qd.gray);
- y = g->controllerRect[kControllerCount - 1].bottom + kDocMargin;
- MoveTo(qd.thePort->portRect.left + kDocMargin,y);
- LineTo(qd.thePort->portRect.right - kDocMargin,y);
- MoveTo(g->keyInfoRect.right + kDocMargin,y);
- LineTo(g->keyInfoRect.right + kDocMargin,qd.thePort->portRect.bottom - kDocMargin);
-
- GoBW();
-
- DrawKeyInfoDoc(d);
-
- if(d->tabField == eKeyField)
- {
- re = g->allKeyRect;
- InsetRect(&re,-4,-4);
- FrameRect(&re);
- }
- }
- }
-
- void Draw1Key(TDoc *d,short n)
- {
- Rect *r;
- char name;
- unsigned char c[30];
-
- if(n < 0)
- goto goHome;
-
- if(n == d->selectedKey && d->sr.zoomed)
- PenSize(2,2);
- else
- PenSize(1,1);
- r = &g->keyRect[n];
- BackColor(whiteColor);
- EraseRect(r);
- GoBlack();
- FrameRectOutside(r);
- name = dKeyPositionToKeyName[n];
- TextFace(bold);
- MoveTo((r->left + r->right - CharWidth(name))>>1,r->top + kDocMargin);
- DrawChar(name);
-
- TextFace(0);
- NumToString(d->sr.pitch[n],c);
- MoveTo((r->left + r->right - StringWidth(c))>>1,r->bottom - 2);
- DrawString(c);
-
- if(d->keyPosition[n])
- InvertRect(r);
- goHome:;
- }
-
-
- void SelectKeyDoc(TDoc *d,short key)
- {
- Rect r;
-
- if(!d->sr.zoomed && key >= 0)
- goto goHome;
-
- if(key != d->selectedKey)
- {
- GoBW();
- if(d->selectedKey >= 0)
- {
- r = g->keyRect[d->selectedKey];
- InsetRect(&r,-2,-2);
- RGBFore(40000,63000,40000);
- RGBBack(40000,63000,40000);
- FrameRect(&r);
-
- GoBW();
- }
-
- if(key >= 0)
- {
- PenSize(2,2);
- FrameRectOutside(&g->keyRect[key]);
- }
-
- g->lastKeyDown = d->selectedKey = key;
- DrawKeyNumbersDoc(d);
- }
- goHome:;
- }
-
- void SelectFieldDoc(TDoc *d,short f)
- {
- Rect re;
-
- if(!d->sr.zoomed && f)
- goto goHome;
-
- re = g->allKeyRect;
- InsetRect(&re,-4,-4);
-
- if(d->tabField != f)
- {
- BlinkTextCursorDoc(d,-1);
- if(d->tabField == eKeyField)
- {
- PenNormal();
- RGBFore(40000,63000,40000);
- RGBBack(40000,63000,40000);
- FrameRect(&re);
- }
-
- d->tabField = f;
-
- if(d->tabField == eKeyField)
- {
- PenNormal();
- FrameRect(&re);
- }
-
- DrawKeyNumbersDoc(d);
- BlinkTextCursorDoc(d,1);
- }
- goHome:;
- }
-
-
- void DrawKeyInfoDoc(TDoc *d)
- {
- short key;
-
- key = d->selectedKey;
-
- GoBW();
- RGBBack(40000,63000,40000);
- EraseRect(&g->keyInfoRect);
-
- MoveTo(g->keyInfoRect.left,g->keyInfoRect.top + kTextAllowance);
- TextFont(0);
- TextSize(12);
- TextFace(0);
- DrawString("\pKeyboard Setup");
-
- TextFont(3);
- TextSize(9);
- MoveTo(kKeyInfoHDivider,g->keyInfoRect.top + 2*kTextAllowance);
- DrawStringRight("\pKey= ");
-
- MoveTo(kKeyInfoHDivider,g->pitchInfoRect.bottom - 4);
- DrawStringRight("\pPitch: ");
-
- MoveTo(kKeyInfoHDivider,g->velInfoRect.bottom - 4);
- DrawStringRight("\pVelocity: ");
-
- DrawKeyNumbersDoc(d);
- }
-
-
- void FrameNumbersField(Rect *r)
- {
- Rect re;
-
- re = *r;
- FrameRect(&re);
- InsetRect(&re,+1,+1);
- EraseRect(&re);
- }
-
- void DrawKeyNumbersDoc(TDoc *d)
- {
- short x;
- short key;
- Rect r;
-
- key = d->selectedKey;
-
- if(key >= 0)
- Draw1Key(d,key);
-
- GoBW();
- RGBBack(40000,63000,40000);
- r = g->keyInfoRect;
- r.top += kTextAllowance + kDocMargin - 4;
- r.left = kKeyInfoHDivider;
- EraseRect(&r);
- GoBW();
-
- x = kKeyInfoHDivider + 5;
-
- TextSize(9);
- TextFace(3);
- TextFace(0);
-
- MoveTo(x,g->keyInfoRect.top + 2*kTextAllowance);
- DrawChar('\'');
- TextFace(bold);
- DrawChar(dKeyPositionToKeyName[key]);
- TextFace(0);
- DrawChar('\'');
- TextFace(bold);
-
- d->textCursorPt.h = -100;
-
- MoveTo(x,g->pitchInfoRect.bottom - 4);
- if(d->tabField == ePitchField)
- {
- FrameNumbersField(&g->pitchInfoRect);
- DrawNoteName(d->sr.pitch[key]);
- GetPen(&d->textCursorPt);
- }
- else
- DrawNoteName(d->sr.pitch[key]);
-
- MoveTo(x,g->velInfoRect.bottom - 4);
- if(d->tabField == eVelField)
- {
- FrameNumbersField(&g->velInfoRect);
- DrawNum(d->sr.vel[key]);
- GetPen(&d->textCursorPt);
- }
- else
- DrawNum(d->sr.vel[key]);
- }
-
-
-
-
- void ClickDoc(short n,Point p,short mods)
- /*
- * Come here for a click in the window.
- */
- {
- #pragma unused (mods)
- Rect r;
- short i;
- TDoc *d;
-
- d = &gDoc[n-kFirstDocWindow];
-
- for(i = 0; i<kControllerCount; i++)
- {
- if(PtInRect(p,&g->controllerRect[i]))
- {
- TrackMIDIController(n,p,i,d);
- goto goHome;
- }
- }
-
- if(PtInRect(p,&g->allKeyRect))
- {
- for(i = 0; i<kKeyCount; i++)
- {
- if(PtInRect(p,&g->keyRect[i]))
- {
- SelectKeyDoc(d,i);
- SelectFieldDoc(d,eKeyField);
- g->lastKeyDown = i;
- }
- }
- }
-
- else if(PtInRect(p,&g->pitchInfoRect))
- SelectFieldDoc(d,ePitchField);
-
- else if(PtInRect(p,&g->velInfoRect))
- SelectFieldDoc(d,eVelField);
-
- goHome:;
- }
-
- void TrackMIDIController(short n,Point p,short controller,TDoc *d)
- {
- Rect r,slopR;
- long x,lastX;
- MIDIPacket b;
-
- r = g->controllerRect[controller];
-
- if(controller == 0)
- {
- b.data[0] = 0xE0 + d->sr.channel;
- b.data[1] = 0;
- }
- else
- {
- b.data[0] = 0xB0 + d->sr.channel;
- if(controller == 1)
- b.data[1] = 1;
- else
- b.data[1] = 7;
- }
-
- slopR = r;
- InsetRect(&slopR,-10,-10);
-
- b.len = 9;
- b.flags = 0x80;
-
- lastX = -1;
- do
- {
- IdleDoc(n,true);
- x = 127L * (p.h - r.left) / (r.right - r.left);
- if(x < 0)
- x = 0;
- else if(x > 127)
- x = 127;
-
- if(x != lastX)
- {
- b.data[2] = x;
- MIDIWritePacket(d->outPort,&b);
- lastX = x;
- }
-
- GetMouse(&p);
- } while(StillDown());
-
- }
-
-
- static unsigned char *dNoteName[] =
- {
- "\pC",
- "\pC#",
- "\pD",
- "\pD#",
- "\pE",
- "\pF",
- "\pF#",
- "\pG",
- "\pG#",
- "\pA",
- "\pA#",
- "\pB"
- };
-
- void DrawNoteName(short noteNumber)
- /*
- * Print the MIDI note number as a string
- */
- {
- short o,n;
-
- if(noteNumber < 0)
- noteNumber = 0;
- else if(noteNumber > 127)
- noteNumber = 127;
-
- o = noteNumber/12;
- n = noteNumber % 12;
-
- DrawString(dNoteName[n]);
- DrawNum(o-2);
- DrawString("\p (");
- DrawNum(noteNumber);
- DrawChar(')');
- }
-
-
-
-
- void KeyDoc(short n,short key,short code, short mods)
- {
- short *val;
- short z;
- TDoc *d;
- short lastPitch,lastVel;
-
- d = &gDoc[n-kFirstDocWindow];
-
- if(!d->sr.zoomed)
- goto goHome;
-
- lastPitch = d->sr.pitch[d->selectedKey];
- lastVel = d->sr.vel[d->selectedKey];
-
- if(d->tabField != eVelField)
- val = d->sr.pitch;
- else
- val = d->sr.vel;
-
- val += d->selectedKey;
-
- if(key >= '0' && key <= '9' && (d->tabField != eKeyField || code >= 65))
- {
- *val = 10 * (*val % 10) + (key - '0');
- DrawKeyNumbersDoc(d);
- d->changed = true;
- }
- else
- switch(key)
- {
- case '+':
- case '=':
- z = 1;
- bumpVal:
- if(mods & shiftKey)
- z *= 10;
- *val = (z + *val) & 0x7F;
- DrawKeyNumbersDoc(d);
- d->changed = true;
- break;
-
- case '-':
- case '_':
- z = -1;
- goto bumpVal;
-
- case 9: /* tab */
- if(mods & shiftKey)
- {
- z = d->tabField - 1;
- if(z <= eFirstField)
- z = eLastField - 1;
- }
- else
- {
- z = d->tabField + 1;
- if(z >= eLastField)
- z = eFirstField + 1;
- }
- SelectFieldDoc(d,z);
- break;
-
- case 28: /* left arrow */
- z = (d->selectedKey + kKeyCount-1) % kKeyCount;
- arrowMove:
- if(mods & optionKey)
- {
- d->sr.pitch[z] = (lastPitch + 1) & 0x7F;
- d->sr.vel[z] = lastVel;
- d->changed = true;
- }
- SelectKeyDoc(d,z);
- break;
-
- case 29: /* right arrow */
- doRightArrow:
- z = (d->selectedKey + 1) % kKeyCount;
- goto arrowMove;
- break;
-
- case 30: /* up arrow */
- z = d->selectedKey - kKeyColumns;
- if(z == -kKeyColumns)
- z = kKeyCount-1;
- if(z < 0)
- z += kKeyCount-1;
- goto arrowMove;
-
- case 31: /* down arrow */
- z = d->selectedKey + kKeyColumns;
- if(z == kKeyCount+kKeyColumns-1)
- z = 0;
- if (z >= kKeyCount)
- z -= kKeyCount-1;
- goto arrowMove;
- }
-
- FixUpMenus(d);
- goHome:;
- }
-
- void MoveDoc(short n)
- {
- TDoc *d;
-
- d = &gDoc[n-kFirstDocWindow];
-
- d->littleChanged = true;
- FixUpMenus(d);
- }
-
- void ZoomDoc(short n)
- {
- short w,h;
- TDoc *d;
-
- d = &gDoc[n-kFirstDocWindow];
-
- d->sr.zoomed = !d->sr.zoomed;
- if(d->sr.zoomed)
- {
- w = g->zoomedBounds.right;
- h = g->zoomedBounds.bottom;
- SelectKeyDoc(d,g->lastKeyDown >= 0 ? g->lastKeyDown : 0);
- SelectFieldDoc(d,eKeyField);
- }
- else
- {
- w = g->unzoomedBounds.right;
- h = g->unzoomedBounds.bottom;
- SelectFieldDoc(d,0);
- SelectKeyDoc(d,-1);
- SelectFieldDoc(d,0);
- }
-
- SizeWindow(d->w,w,h,true);
-
- d->changed = true;
- FixUpMenus(d);
- }
-
- short CloseDoc(short n)
- /*
- * Close that window...
- * Return 'true' if the
- * user canceled the save. This is useful
- * when 'quitting' but then cancelling.
- */
- {
- short x;
- TDoc *d;
- Boolean cancelSave;
-
- d = &gDoc[n - kFirstDocWindow];
-
- DeactivateDoc(n);
- SquelchAllKeys(d);
-
- if(d->used && d->changed)
- {
- x = EasyDialogMessage(0,d->docSpec.name,"\pSave changes before closing this document?",
- kEasyDialogSaveDiscardCancel);
- if(x == 2)
- cancelSave = true;
- else if(x == 0)
- cancelSave = SaveDoc(n,0,0);
- else
- cancelSave = false;
- }
- else
- cancelSave = false;
-
- if(!cancelSave)
- {
- UninstallWindow(n);
- g->thisDoc = 0;
- MIDIRemovePort(d->outPort);
- d->used = false;
- gDocCount--;
- }
-
- FixUpMenus(0);
-
- return cancelSave;
- }
-
- void FixUpMenus(TDoc *d)
- /*
- * Make menus suitable for document d,
- * where d=nil means deactivate
- */
- {
- short moreDocs;
-
- moreDocs = SignIt(gDocCount<kDocMax);
-
- SetMenuItem(mNew,moreDocs,0,0,nil);
- SetMenuItem(mOpen,moreDocs,0,0,nil);
-
- FixUpPortListMenu(d);
-
- if(d)
- {
- SetMenuItem(mSave,SignIt(d->changed || d->littleChanged),0,0,nil);
- SetMenuItem(mClose,1,0,0,nil); /* enable "Close" menu item */
- SetMenuItemRange(mFirstDocActive,mLast,1,-1);
- SetMenuItem(mBackgroundPlay,1,SignIt(d->sr.backgroundPlay),18,nil);
- }
- else
- {
- SetMenuItem(mSave,-1,0,0,nil);
- SetMenuItemRange(mFirstDocActive,mLast,-1,-1);
- }
- }
-
- void FixUpPortListMenu(TDoc *d)
- /*
- * Yeah, we do this every time that the menus
- * might change, bunch of gethandle this
- * and that. Okay? Keeps the menus looking good.
- */
- {
- short i,j,k;
- short portCount;
- MIDIIDList **clients,**ports;
- OSType portID,clientID;
- MIDIPortInfo **portInfo;
- short usConnected;
- Str255 s255;
- StringPtr sp;
-
- SetCurrentMenu(mQwertytunes);
- for(i = mPortList; i < mLastPortListItem; i++)
- DeleteMenuItem(i);
-
- portCount = 0;
- clients = MIDIGetClients();
- for(i = 0; i < (**clients).numIDs; i++)
- {
- clientID = (**clients).list[i];
- ports = MIDIGetPorts( clientID );
- for(j = 0; j < (**ports).numIDs; j++)
- {
- portID = (**ports).list[j];
- portInfo = MIDIGetPortInfo(clientID,portID);
- if( (**portInfo).portType == midiPortTypeInput)
- {
- usConnected = -1;
- if(d)
- for(k = 0; k < (**portInfo).numConnects; k++)
- {
- if( (**portInfo).cList[k].clientID == g->midiClientID
- && (**portInfo).cList[k].portID == d->outPortID)
- usConnected = 1;
- }
- g->clientList[portCount] = clientID;
- g->portList[portCount] = portID;
- sp = g->portName[portCount];
- MIDIGetClientName(clientID,sp);
- MIDIGetPortName(clientID,portID,s255);
- ConcatenatePStrings(sp,"\p, ");
- ConcatenatePStrings(sp,s255);
- InstallMenuItem(g->portName[portCount],MIDIConnectDoc,
- (mPortList + portCount) * SignIt(d != 0));
- SetMenuItem(mPortList + portCount,SignIt(d!=0),usConnected,18,nil);
- portCount ++;
- if(portCount == kMaxPortCount)
- {
- DisposeHandle((Handle)portInfo);
- DisposeHandle((Handle)ports);
- DisposeHandle((Handle)clients);
- goto goHome;
- }
- }
- DisposeHandle((Handle)portInfo);
- }
- DisposeHandle((Handle)ports);
- }
- DisposeHandle((Handle)clients);
-
- goHome:;
- }
-
-
- void MIDIConnectDoc(short n,short item, short ref)
- {
- TDoc *d;
- MIDIPortInfo **portInfo;
- short i,j;
- OSType clientID,portID;
-
- d = &gDoc[n-kFirstDocWindow];
-
- ref -= mPortList;
- clientID = g->clientList[ref];
- portID = g->portList[ref];
- portInfo = MIDIGetPortInfo(g->midiClientID,d->outPortID);
-
- /*
- * See if we're already connected
- */
- for(i = 0; i < (**portInfo).numConnects; i++)
- {
- if( (**portInfo).cList[i].clientID == clientID
- && (**portInfo).cList[i].portID == portID)
- {
- MIDIUnConnectData(g->midiClientID,d->outPortID,clientID,portID);
- goto x;
- }
- }
-
- MIDIConnectData(g->midiClientID,d->outPortID,clientID,portID);
- x:
- DisposeHandle((Handle)portInfo);
- d->changed = true;
- FixUpMenus(d);
- }
-
-
- void FixUpDocConnectionList(TDoc *d)
- /*
- * Just before saving a doc,
- * see who we're connected to
- * and remember these things.
- */
- {
- MIDIPortInfo **portInfo;
- short portCount,i;
-
- portInfo = MIDIGetPortInfo(g->midiClientID,d->outPortID);
- portCount = (**portInfo).numConnects;
- if(portCount > kMaxPortCount)
- portCount = kMaxPortCount;
-
- for(i = 0; i < portCount; i++)
- {
- d->sr.portList[i] = (**portInfo).cList[i].portID;
- d->sr.clientList[i] = (**portInfo).cList[i].clientID;
- }
- d->sr.portCount = portCount;
- DisposeHandle((Handle)portInfo);
- }
-
-
- void ActivateDoc(short n)
- {
- TDoc *d;
-
- d = &gDoc[n-kFirstDocWindow];
-
- FixUpMenus(d);
-
- g->thisDoc = d;
- if(d->selectedKey >= 0)
- g->lastKeyDown = d->selectedKey;
- BlinkTextCursorDoc(d,1);
- }
-
- void DeactivateDoc(short n)
- {
- TDoc *d;
-
- d = &gDoc[n-kFirstDocWindow];
- if(!d->sr.backgroundPlay)
- {
- SquelchAllKeys(d);
- g->thisDoc = 0;
- }
-
-
- FixUpMenus(nil);
-
- BlinkTextCursorDoc(d,-1);
- }
-
- void BlinkTextCursorDoc(TDoc *d,short what)
- /*
- * what = 1 to start blinking, 0 to blink, and -1 to remove it.
- */
- {
- long t;
-
- GoBW();
- PenMode(patXor);
- MoveTo(d->textCursorPt.h,d->textCursorPt.v);
-
- t = TickCount();
-
- switch(what)
- {
- case 1:
- d->textCursorBlink = true;
- doBlink:
- d->textCursorTicks = t + kCursorBlinkTicks;
- Line(0,-9);
- d->textCursorPhase = !d->textCursorPhase;
- break;
-
- case 0:
- if(d->textCursorBlink && t >= d->textCursorTicks)
- goto doBlink;
- break;
-
- case -1:
- d->textCursorBlink = false;
- if(d->textCursorPhase)
- goto doBlink;
- }
- GoBW();
-
- }
-
-
- void IdleDoc(short n,Boolean front)
- {
- short i;
- TDoc *d;
- Boolean snik;
-
- d = &gDoc[n-kFirstDocWindow];
-
- if(front)
- {
- BlinkTextCursorDoc(d,0);
-
- if(d->tabField == eKeyField)
- if((g->lastKeyDown >= 0) && (d->selectedKey != g->lastKeyDown))
- SelectKeyDoc(d,g->lastKeyDown);
-
- for(i = 0; i < kKeyCount; i++)
- {
- snik = g->keyPosition[i]; /* since it _could_ change even now... */
- if(snik != d->keyPosition[i])
- {
- InvertRect(&g->keyRect[i]);
- d->keyPosition[i] = snik;
- }
- }
- }
-
- }
-
-
- void BackgroundPlayDoc(short n,short item, short ref)
- {
- TDoc *d;
-
- d = &gDoc[n-kFirstDocWindow];
-
- d->sr.backgroundPlay = !d->sr.backgroundPlay;
- d->changed = true;
- FixUpMenus(d);
- }
-
- void SelectInstrumentDoc(short n,short item, short ref)
- {
- Boolean took;
- TDoc *d;
- MIDIPacket packet;
-
- d = &gDoc[n-kFirstDocWindow];
- SquelchAllKeys(d);
-
- do
- took = EasyDialogGetNumber("\pSelect Instrument",
- "\pSelect a new instrument number, 1 - 128:",
- &d->instrument);
- while(took && (d->instrument < 1 || d->instrument > 16384));
-
- if(took)
- {
- packet.flags = 0x80;
-
- packet.len = 9;
- packet.data[0] = 0xB0 + d->sr.channel;
- packet.data[1] = 0;
- packet.data[2] = (d->instrument-1) >> 7;
- MIDIWritePacket(d->outPort,&packet);
-
- packet.len = 9;
- packet.data[0] = 0xB0 + d->sr.channel;
- packet.data[1] = 32;
- packet.data[2] = 0;
- MIDIWritePacket(d->outPort,&packet); // send bank lsb of 0
-
- packet.len = 8;
- packet.data[0] = 0xC0 + d->sr.channel;
- packet.data[1] = (d->instrument-1) & 0x7F;
- MIDIWritePacket(d->outPort,&packet);
- }
- }
-
- void SelectChannelDoc(short n,short item, short ref)
- {
- Boolean took;
- TDoc *d;
- long newChan;
-
- d = &gDoc[n-kFirstDocWindow];
- SquelchAllKeys(d);
-
- newChan = d->sr.channel + 1;
- d->sr.channel++;
-
- do
- took = EasyDialogGetNumber("\pSelect MIDI Channel",
- "\pSelect a new MIDI channel, 1 - 16:",
- &newChan);
- while(took && (d->sr.channel < 1 || d->sr.channel > 16));
-
- d->sr.channel = newChan - 1;
- }
-
- static Str255 gMS = "\p";
-
- static void MIDIMessageDoc(short n,short item, short ref)
- {
- Boolean took;
- TDoc *d;
- MIDIPacket packet;
- short hLen,sLen;
- unsigned char *w;
- short phase;
- short d1,d2;
-
-
- d = &gDoc[n-kFirstDocWindow];
- SquelchAllKeys(d);
-
- took = EasyDialogGetString("\pSend MIDI Message",
- "\pEnter message in hexadecimal:",
- gMS,255);
-
- if(took)
- {
- hLen = 0;
- phase = 0;
- sLen = gMS[0];
- w = &gMS[1];
-
- while(sLen)
- {
- if(*w >= 'a' && *w <= 'f')
- d1 = *w - 'a' + 10;
- else if(*w >= 'A' && *w <= 'F')
- d1 = *w - 'A' + 10;
- else if(*w >= '0' && *w <= '9')
- d1 = *w - '0';
- else
- goto blankchar;
-
- if(phase)
- {
- phase = 0;
- packet.data[hLen] = d2+d1;
- hLen++;
- }
- else
- {
- phase = 1;
- d2 = d1<<4;
- }
- blankchar:
- w++;
- sLen--;
- }
-
- packet.flags = 0x80;
- packet.len = 6 + hLen;
- packet.tStamp = 0;
- MIDIWritePacket(d->outPort,&packet);
- }
-
- }
-
-
- pascal void PeriodicThing(long currentTime, long refCon)
- {
- TGlobals *g;
- char diffMask[16];
- char *newMask;
- char x;
- char mask;
- short i,bit,key;
- Boolean cmdKeyDown;
- MIDIPacket packet;
- TDoc *d;
-
- g = (void *)refCon;
- d = g->thisDoc;
-
- newMask = (char *)0x174; /* Low-mem keyboard mask */
-
- for(i = 15; i>= 0; i--)
- diffMask[i] = g->keyMask[i] ^ newMask[i];
-
- cmdKeyDown = (newMask[6] & 0x80) != 0;
-
-
- for(i = 15; i>=0; i--)
- {
- x = diffMask[i];
- mask = 0x01;
- bit = 0;
- while(x && mask)
- {
- if(x & mask)
- {
- key = g->keyCodeToKeyPosition[(i<<3) + bit];
- if(key >= 0)
- {
- if(d)
- {
- packet.flags = 0x80;
- packet.len = 9;
- packet.data[0] = 0x90 + d->sr.channel;
- packet.data[1] = d->sr.pitch[key];
- }
-
- if(newMask[i] & mask && !cmdKeyDown)
- { /* key-down */
- g->keyPosition[key] = true;
- g->lastKeyDown = key;
- if(d)
- packet.data[2] = d->sr.vel[key];
- }
- else
- { /* key-up */
- g->keyPosition[key] = false;
- if(d)
- packet.data[2] = 0;
- }
-
- if(d)
- MIDIWritePacket(d->outPort,&packet);
- }
- }
- mask <<= 1;
- ++ bit;
- }
- }
-
- for(i = 15; i>= 0; i--)
- g->keyMask[i] = newMask[i];
- }
-
-
- void SquelchAllKeys(TDoc *d)
- {
- MIDIPacket packet;
- short i;
-
- for(i = 0; i < kKeyCount; i++)
- {
- if(g->keyPosition[i])
- {
- g->keyPosition[i] = false;
-
- packet.flags = 0x80;
- packet.len = 9;
- packet.data[0] = 0x90 + d->sr.channel;
- packet.data[1] = d->sr.pitch[i];
- packet.data[2] = 0; /* vel = 0 -> keyoff */
-
- MIDIWritePacket(d->outPort,&packet);
- }
- }
- }
-
-
-
- void LetsQuit(void)
- {
- short i;
- TDoc *d;
- Boolean cancelQuit;
-
- cancelQuit = false;
- for(i = 0; i<kDocMax && !cancelQuit; i++)
- {
- d = &gDoc[i];
-
- if(d->used)
- cancelQuit = CloseDoc(i + kFirstDocWindow);
- }
-
- if(!cancelQuit)
- gQuitApp++;
- }
-
-
- void NewDoc(void)
- {
- short i;
-
- for(i = 0; i<kDocMax; i++)
- {
- if(!gDoc[i].used)
- {
- NewDocFromSaveRecord(i,nil);
- goto goHome;
- }
- }
- goHome:;
- }
-
-
- void NewDocFromSaveRecord(short docNumber,TSaveRecord *sr)
- {
- TDoc *d;
- Rect r;
- Rect docRect;
- short i,j;
-
- d = &gDoc[docNumber];
-
- d->changed = false;
-
- docRect = g->unzoomedBounds;
- if(sr)
- {
- d->sr = sr->sr;
- gStaggerWindows = false;
- if(d->sr.zoomed)
- docRect = g->zoomedBounds;
- OffsetRect(&docRect,sr->windowRect.left,sr->windowRect.top);
-
- d->everSaved = true;
- d->littleChanged = false;
-
- if(d->sr.zoomed)
- {
- if(g->lastKeyDown >= 0)
- d->selectedKey = g->lastKeyDown;
- else
- d->selectedKey = g->lastKeyDown = 0;
- d->tabField = eKeyField;
- }
- else
- {
- d->selectedKey = -1;
- d->tabField = 0;
- }
-
- if(d->sr.portCount > kMaxPortCount)
- d->sr.portCount = 0;
-
- }
- else
- {
- gStaggerWindows = true;
- OffsetRect(&docRect,100,100);
-
- CopyPString(d->docSpec.name,"\pUntitled");
- d->everSaved = false;
-
- d->sr.channel = 0;
- for(i = 0; i < kKeyCount; i++)
- {
- d->sr.pitch[i] = i + 48;
- d->sr.vel[i] = 64;
- d->sr.dur[i] = 0; /* key-controlled duration */
- }
- d->sr.zoomed = false;
- d->sr.backgroundPlay = false;
- d->littleChanged = true;
- d->selectedKey = -1;
- d->tabField = 0;
- d->sr.portCount = 0;
- }
-
- /*
- * Clear the keyboard mask
- */
- for(i = 0; i < kKeyCount; i++)
- d->keyPosition[i] = 0;
-
- d->instrument = 1;
-
- d->textCursorPhase = 0;
- d->textCursorBlink = false;
- d->textCursorPt.h = -100;
-
- /*
- * MIDI port
- */
- {
- MIDIPortParams mp;
- OSErr thisError;
-
- d->outPortID = 'dvb!';
-
- mp.portID = d->outPortID;
- mp.portType = midiPortTypeOutput;
- mp.timeBase = g->timePort;
- mp.offsetTime = 0;
- mp.readHook = 0;
- mp.refCon = 0;
- BlockMove(d->docSpec.name,&mp.name,32);
- thisError = MIDIAddPort(g->midiClientID,0,&d->outPort,&mp); /* error?? */
- }
-
- for(i = 0; i < d->sr.portCount; i++)
- MIDIConnectData(g->midiClientID,d->outPortID,
- d->sr.clientList[i],d->sr.portList[i]);
-
- d->w = InstallWindow(docNumber + kFirstDocWindow,d->docSpec.name,&docRect,
- zoomDocProc,wCopyDraw,
- DrawDoc,ClickDoc,KeyDoc,(void *)CloseDoc,
- ActivateDoc,DeactivateDoc,IdleDoc);
- SetWindowMoveProc(docNumber + kFirstDocWindow,MoveDoc);
- SetWindowZoomProc(docNumber + kFirstDocWindow,ZoomDoc);
-
- d->used = true;
-
- gDocCount++;
- goHome:;
- }
-
- void About(void)
- {
- if(g->thisDoc && !g->thisDoc->sr.backgroundPlay)
- SquelchAllKeys(g->thisDoc);
- EasyDialogMessage(0,(StringPtr)0x910,
- "\pVersion 0.6 by David Van Brink",
- kEasyDialogOkay);
- }
-
- void InitVars(void)
- /*
- * Called once at startup: yes, it
- * inits the vars.
- */
- {
- TDoc *dp;
- short i,j;
- Rect r,ar;
-
- for(i = 0; i<kDocMax; i++)
- {
- dp = &gDoc[i];
- dp->used = false;
- }
- gDocCount = 0;
-
- g = (void *)NewPtr(sizeof(TGlobals));
-
- /*
- * Build up a list of rectangles for
- * drawing the keyboard.
- */
- r.top = r.left = kDocMargin;
- r.bottom = r.top + kKeyHeight;
- r.right = r.left + kKeyWidth;
- for(i = 0; i < kKeyRows; i++)
- {
- OffsetRect(&r,kDocMargin + i * kKeyRowBump - r.left,0);
- for(j = 0; j < kKeyColumns; j++)
- {
- g->keyRect[i * kKeyColumns + j] = r;
- if(i || j)
- UnionRect(&ar,&r,&ar);
- else
- ar = r;
- OffsetRect(&r,kKeyWidth + kKeyMargin,0);
- }
- OffsetRect(&r,0,kKeyHeight + kKeyMargin);
- }
- g->allKeyRect = ar;
-
- for(i = 0; i<kControllerCount; i++)
- {
- r.left = g->allKeyRect.left;
- r.right = g->allKeyRect.right;
- r.top = g->allKeyRect.bottom + kDocMargin;
- r.bottom = r.top + kDocMargin;
- OffsetRect(&r,0,i * kDocMargin * 2);
- g->controllerRect[i] = r;
- }
-
- UnionRect(&ar,&g->controllerRect[kControllerCount - 1],&ar);
-
- /*
- * Position of pitch and key info.
- */
- g->keyInfoRect.left = g->allKeyRect.left;
- g->keyInfoRect.right = g->keyInfoRect.left + kKeyInfoWidth;
- g->keyInfoRect.top = g->controllerRect[kControllerCount - 1].bottom + 1 + kDocMargin;
- g->keyInfoRect.bottom = g->keyInfoRect.top + kKeyInfoHeight;
-
- g->pitchInfoRect.left = kKeyInfoHDivider + 2;
- g->pitchInfoRect.top = g->keyInfoRect.top + 3*kTextAllowance - 11;
- g->pitchInfoRect.right = g->keyInfoRect.right - 3;
- g->pitchInfoRect.bottom = g->pitchInfoRect.top + 15;
-
- g->velInfoRect = g->pitchInfoRect;
- OffsetRect(&g->velInfoRect,0,kTextAllowance);
-
-
- /*
- * Window size
- * zoomed and unzoomed.
- */
- g->unzoomedBounds = ar;
- InsetRect(&g->unzoomedBounds,-kDocMargin,-kDocMargin);
- UnionRect(&ar,&g->keyInfoRect,&ar);
- g->zoomedBounds = ar;
- InsetRect(&g->zoomedBounds,-kDocMargin,-kDocMargin);
-
-
- /*
- * Transform the keycode list into
- * a code->position table.
- */
- for(i = 0; i< 256; i++)
- g->keyCodeToKeyPosition[i] = -1;
- for(i = 0; i < kKeyCount; i++)
- g->keyCodeToKeyPosition[dKeyPositionToKeyCode[i]] = i;
- g->lastKeyDown = 0;
-
- /*
- * Clear the keyboard masks
- */
- for(i = 15; i>=0; i--)
- g->keyMask[i] = 0;
- for(i = 0; i < kKeyCount; i++)
- g->keyPosition[i] = false;
-
- g->thisDoc = 0;
-
- /*
- * Sign in as a MIDI client.
- */
- {
- OSErr thisError;
- long midiClientID;
- MIDIPortParams mp;
-
- midiClientID = 'qwTu';
- signin:
- thisError = MIDISignIn(midiClientID,0,nil,(StringPtr)0x910);
- if(thisError == midiDupIDErr) /* client already logged in? */
- { /* no problem, bump to next ID. */
- midiClientID++;
- goto signin;
- }
-
- if(thisError)
- Debugger(); /* should handle errors, you know??? */
-
- g->midiClientID = midiClientID;
-
- g->timePortID = 'time';
-
- mp.portID = g->timePortID;
- mp.portType = midiPortTypeTimeInv;
- mp.timeBase = 0;
- mp.offsetTime = 0;
- mp.readHook = 0;
- mp.refCon = (long) g;
- mp.initClock.sync = midiInternalSync;
- mp.initClock.curTime = 0;
- mp.initClock.format = midiFormatMSec;
- BlockMove("\ptime",&mp.name,32);
- thisError = MIDIAddPort(g->midiClientID,0,&g->timePort,&mp); /* error?? */
- MIDIStartTime(g->timePort);
- }
-
-
- MIDIWakeUp(g->timePort,0,4,PeriodicThing);
- }
-
- void Bootstrap()
- {
- long x;
-
- x = SndDispVersion(midiToolNum);
- if(x == 0)
- {
- x = EasyDialogMessage(0,(StringPtr)0x910,"\pThis application requires the MIDI Manager",
- kEasyDialogOkay);
- ExitToShell();
- }
-
-
- /*** File Menu ***/
- InstallMenu("\pFile",nil,0);
- InstallMenuItem("\pNew/N",(void *)NewDoc,mNew);
- InstallMenuItem("\pOpen…/O",OpenDoc,mOpen);
- InstallMenuItem("\pClose/W",(void *)CloseDoc,-mClose);
- InstallMenuItem("\p(-",nil,0);
- InstallMenuItem("\pSave/S",(void *)SaveDoc,-mSave);
- InstallMenuItem("\pSave As…",(void *)SaveAsDoc,-mSaveAs);
- InstallMenuItem("\pQuit/Q",(void *)LetsQuit,0);
-
- /*** Edit Menu ***/
- InstallEditMenu(nil,nil,nil,nil,nil);
-
- /*** Qwertytunes Menu ***/
- InstallMenu("\pQwertytunes",nil,-mQwertytunes);
- InstallMenuItem("\pBackground Performance/B",BackgroundPlayDoc,-mBackgroundPlay);
- InstallMenuItem("\pSelect Instrument…/I",SelectInstrumentDoc,-mSelectInstrument);
- InstallMenuItem("\pSelect MIDI Channel…/L",SelectChannelDoc,-mSelectChannel);
- InstallMenuItem("\pSend MIDI Message…/M",MIDIMessageDoc,-mMIDIMessage);
- InstallMenuItem("\p(-",nil,0);
-
-
-
-
- {
- Str63 s;
-
- CopyPString(s,"\pAbout ");
- ConcatenatePStrings(s,(StringPtr)0x910);
- ConcatenatePStrings(s,"\p…");
- SetAbout(s,0,About);
- }
-
- SetMasterOpenDocProc(OpenDocSpec);
- SetMasterQuitAppProc(LetsQuit);
-
- InitVars();
- }
-
- void Hatstrap()
- /*
- * clean up
- */
- {
- MIDISignOut(g->midiClientID);
- }
-